<?php
/**
 * Created by PhpStorm.
 * User: yhf
 * Date: 2019-01-22
 * Time: 20:06
 */

namespace app\api\service;

use app\lib\exception\TokenException;
use app\lib\exception\UserException;
use app\lib\exception\wxChatException;
use think\Exception;
use app\api\model\User as UserModel;

class UserToken extends Token
{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    function __construct($code)
    {
        $this->code = $code;
        $this->wxAppID = config('wx.app_id');
        $this->wxAppSecret = config('wx.app_secret');
        $this->wxLoginUrl = sprintf(config('wx.login_url'),$this->wxAppID,$this->wxAppSecret,$this->code);
    }

    // 获取openid
    public function get () {
        $result = curl_get($this->wxLoginUrl);
        $wxResult = json_decode($result,true);
        if (empty($wxResult)) {
            throw new Exception('获取session_key及openID时异常，微信内部错误');
        } else {
            $loginFail = array_key_exists('errcode',$wxResult);
            if ($loginFail) {
                $this->processloginError($wxResult);
            } else {
                return $this->grantToken($wxResult);
            }
        }
    }

    // 单发令牌
    private function grantToken ($wxResult) {
        // 拿到 openid
        // 数据库里看一下，这个openID是否存在
        // 如果存在则不处理，如果不存在那会新增一条记录
        // 生成令牌，准备缓存数据，写入缓存
        // 把令牌返回到客户端去
        // key: 令牌
        // value: wxResult,uid,scope

        $openid = $wxResult['openid'];
        $user = UserModel::getByOpenID($openid);
        if (!$user) {
            $uid = $this->newUser($openid);
        } else {
            $uid = $user->id;
        }
        $cachedValue = $this->prepareCachedValue($wxResult,$uid);
        $token = $this->saveToCache($cachedValue);
        return $token;
    }

    // 写入缓存方法
    private function saveToCache ($cachedValue) {
        // 调用基类的令牌生成
        $key = self::generateToken();
        $value = json_encode($cachedValue);
        // 自定义缓存时间
        $expire_in = config('setting.token_expire_in');

        // 存入缓存
        $request = cache($key,$value,$expire_in);

        if (!$request) {
            throw new TokenException([
                'msg' => '服务器缓存异常',
                'errorCode' => 10005
            ]);
        }

        // 返回令牌
        return $key;
    }

    // 准备缓存数据
    private function prepareCachedValue ($wxResult,$uid) {
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;

        return $cachedValue;
    }

    // 插入用户的方法
    private function newUser ($openid) {
        $user = UserModel::create([
            'openid' => $openid
        ]);
        return $user->id;
    }


    // 抛出异常
    private function processloginError ($wxResult) {
        throw new wxChatException([
            'msg' => $wxResult['errmsg'],
            'errorCode' => $wxResult['errcode']
        ]);
    }
}
